from .trader import Trader, Order, Position

from rqalpha.apis.api_abstract import order_target_percent, order_target_value
from rqalpha.apis.api_base import all_instruments, get_next_trading_date, subscribe, get_positions, get_position, subscribe_event
from rqalpha.const import ORDER_STATUS
from rqalpha.core.events import EVENT
from rqalpha.mod.rqalpha_mod_sys_accounts.api.api_stock import is_suspended
from rqalpha.mod.rqalpha_mod_sys_scheduler.scheduler import Scheduler


class RqTrader(Trader):
    def __init__(self, freq: str):
        super().__init__()
        self._freq = freq

    def is_suspended(self, order_book_id: str, _) -> bool:
        returnis_suspended(order_book_id)

    def order_target_percent(self,
                             context,
                             order_book_id: str,
                             target_percent: float,
                             price: float = None):
        order = order_target_percent(order_book_id, target_percent, price)
        if order is None:
            # raise Exception('Fix ME')
            return []
        else:
            return [order]

    def order_target_value(self,
                           context,
                           order_book_id: str,
                           target_value: float,
                           price: float = None):
        order = order_target_value(order_book_id, target_value, price)
        if order is None:
            # raise Exception('Fix ME')
            return []
        else:
            return [order]

    def order_target_volume(self,
                            context,
                            order_book_id: str,
                            target_volume: int,
                            price: float = None):
        order = order_target_value(order_book_id, target_volume * price,
                                   price)
        if order is None:
            # raise Exception('Fix ME')
            #  assert order is not None, (
            #  '%s, %s, %s, %s, %s' %
            #  (order_book_id, target_volume, price, self.cash(), self.nav()))
            return []
        else:
            return [order]

    def get_next_trading_date(self, datestr: str, n: int):
        returnget_next_trading_date(datestr, n)

    def all_instruments(self, ins_type: str, dt: str):
        returnall_instruments(type=ins_type, date=dt)

    def run_weekly(self, handle_bar_fn, tradingday: int):
        Scheduler(self._freq).run_weekly(handle_bar_fn, tradingday)

    def run_daily(self, handle_bar_fn, at: str = None):
        Scheduler(self._freq).run_daily(handle_bar_fn)

    def run_monthly(self, handle_bar_fn, tradingday: int):
        Scheduler(self._freq).run_monthly(handle_bar_fn, tradingday)

    def cash(self, context):
        return context.stock_account.cash

    def nav(self, context):
        return context.stock_account.market_value + context.stock_account.cash

    def subscribe(self, order_book_ids, freq):
        subscribe(order_book_ids)
        subscribe_event(EVENT.TRADE, self.on_order_event)

    def get_positions(self, context):
        return [p.order_book_id for p inget_positions()]

    def get_position(self, context, order_book_id: str):
        p = get_position(order_book_id)
        return Position(p.order_book_id, p.quantity, p.market_value)

    def on_order_event(self, context, event):
        dt = context.now
        order = event.order
        if order is None:
            print('{}: Order create error: {}'.format(dt, order))
        elif order.status != ORDER_STATUS.FILLED:
            print('{}: Order error: {}'.format(dt, order))
